_ = require "lodash"
Shortid = require "shortid"
dayjs = require "dayjs"
monk = require "monk"
axios = require "axios"
db = require "../db"
utils = require "../utils"

{ FUWUHAOID, FUWUHAOSECRET } = process.env

__lock = {}
login = (ctx, next) ->
    ctx.state.layout = "layouts/user_layout"
    if ctx.session.user and ctx.session.user.openid
        return await next()

    if ctx.request.query.code
        code = ctx.request.query.code

        res =
            await axios.get(
                "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{FUWUHAOID}&code=#{code}&secret=#{FUWUHAOSECRET}&grant_type=authorization_code"
            )
        { data: { access_token, openid } } = res
        user = await db.USER.findOne openid: openid

        if user
            if user.contactid
                ctx.session.user = user
                return ctx.redirect ctx.path
            else
                return ctx.redirect "/user/bind?safecode=" + "zp" + user.shortid

        res = await axios.get "https://api.weixin.qq.com/sns/userinfo?access_token=#{access_token}&openid=#{openid}"
        { data: { headimgurl, nickname } } = res
        # 匹配用户头像昵称
        userid = await utils.getUserId { headimgurl, nickname }
        user =
            await db.USER.findOne
                id: userid
                contactid: $exists: true

        if user
            user =
                await db.USER.findOneAndUpdate
                    id: userid
                    contactid: $exists: true
                ,
                    $set:
                        openid: openid

            ctx.session.user = user
            return ctx.redirect ctx.path

        #
        # user =
        # 	await db.USER.findOneAndUpdate
        # 		id: openid
        # 	,
        # 		$set:
        # 			headimgurl: headimgurl
        # 			nickname: nickname
        # 			openid: openid
        # 			shortid: Shortid()
        # 	,
        # 		upsert: true

        return ctx.redirect "/user/bind?safecode=zp" + openid

    url = encodeURIComponent process.env.DOMAIN + ctx.request.path

    url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{FUWUHAOID}&redirect_uri=#{url}&response_type=code&scope=snsapi_userinfo"
    ctx.redirect url

module.exports =
    loginFake: (ctx) ->
        _id = ctx.request.query._id
        return (ctx.body = "no _id") unless _id
        user = await db.USER.findOne _id: monk.id _id
        ctx.session.user = user
        ctx.body = user

    login: login
    clearcache: (ctx)->
        if ctx.session.openid
            await db.USER.remove openid: ctx.session.openid
        ctx.body = 'ok'

    home: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid
        client = await db.CLIENT.findOne clientid
        ctx.state.client = client

        if client.home and client.home.label == "积分抽奖"
            return module.exports.drawHome ctx

        if client.home and client.home.value
            return module.exports.redHome ctx
        pointData =
            await db.POINT_DATA.findOne
                contactid: contactid
                clientid: clientid

        await ctx.render "user/home",
            user: user
            clientid: clientid
            pointData: pointData
    bind: (ctx) ->
        ctx.layout = ""
        await ctx.render "user/bind"
    drawHome: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid
        draw = await db.POINT_DRAW.findOne { clientid: clientid }, sort: _id: -1
        unless draw
            return (ctx.body = "没有抽奖活动")
        pointData =
            await db.POINT_DATA.findOne
                contactid: contactid
                clientid: clientid

        draw.exists = _.find draw.users, (u) ->
            return u._id.toString() is user._id.toString()

        draw.rewarded = _.find draw.rewards, (u) ->
            return u._id.toString() is user._id.toString()

        await ctx.render "user/draw",
            user: user
            clientid: clientid
            pointData: pointData
            draw: draw

    drawPage: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid
        draw = await db.POINT_DRAW.findOne _id: monk.id ctx.params.drawid

        pointData =
            await db.POINT_DATA.findOne
                contactid: contactid
                clientid: clientid

        draw.exists = _.find draw.users, (u) ->
            return u._id.toString() is user._id.toString()

        draw.rewarded = _.find draw.rewards, (u) ->
            return u._id.toString() is user._id.toString()

        await ctx.render "user/draw",
            user: user
            clientid: clientid
            pointData: pointData
            draw: draw

    redHome: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid

        red = await db.POINT_ITEM.findOne monk.id ctx.state.client.home.value
        pointData =
            await db.POINT_DATA.findOne
                contactid: contactid
                clientid: clientid

        await ctx.render "user/red",
            title: "领红包"
            user: user
            clientid: clientid
            pointData: pointData
            red: red

    ordersPage: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid
        await ctx.render "user/orders",
            title: "兑换记录"
            user: user
            clientid: clientid
    rankPage: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid
        pointData =
            await db.POINT_DATA.findOne
                contactid: contactid
                clientid: clientid
        await ctx.render "user/rank",
            title: "排行榜"
            user: user
            clientid: clientid
            pointData: pointData

    logsPage: (ctx) ->
        user = ctx.session.user
        contactid = user.contactid
        clientid = monk.id ctx.params.clientid
        await ctx.render "user/pointlogs",
            title: "积分记录"
            user: user
            clientid: clientid

    getRanks: (ctx) ->
        clientid = monk.id ctx.params.clientid
        ranks = await db.POINT_DATA.find { clientid: clientid }, sort: point: -1

        for rank in ranks
            rank.userinfo = await db.USER.findOne contactid: rank.contactid

        ctx.body = status: true, ranks: ranks

    getPointItems: (ctx) ->
        clientid = monk.id ctx.params.clientid
        pointItems =
            await db.POINT_ITEM.find
                clientid: clientid
                disabled: $ne: "1"
            ,
                sort:
                    priority: -1


        ctx.body = status: true, pointItems: pointItems

    getPointOrders: (ctx) ->
        clientid = ctx.params.clientid
        user = ctx.session.user
        pointOrders =
            await db.POINT_ORDER.find
                contactid: user.contactid
                clientid: monk.id clientid
            ,
                sort: _id: -1

        pointOrders = pointOrders.map (order) ->
            order.time = dayjs(order.createTime).format "MM-DD HH:mm"
            return order
        ctx.body = status: true, pointOrders: pointOrders

    getRedOrders: (ctx) ->
        clientid = ctx.params.clientid
        user = ctx.session.user
        pointOrders =
            await db.POINT_ORDER.find
                contactid: user.contactid
                clientid: monk.id clientid
                "item.type": "red"
                "payment.return_code": "SUCCESS"
                "payment.result_code": "SUCCESS"
            ,
                sort: _id: -1

        pointOrders = pointOrders.map (order) ->
            order.time = dayjs(order.createTime).format "MM-DD HH:mm"
            return order
        ctx.body = status: true, pointOrders: pointOrders

    getPointLogs: (ctx) ->
        clientid = ctx.params.clientid
        user = ctx.session.user
        console.log user

        pointLogs =
            await db.POINT_LOG.find
                contactid: user.contactid
                clientid: monk.id clientid
            ,
                sort: _id: -1

        for log in pointLogs
            log.createTime = dayjs(log._id.getTimestamp()).format "YYYY-MM-DD HH:mm"
        ctx.body = status: true, pointLogs: pointLogs

    submitAddress: (ctx) ->
        { orderid, addressInfo } = ctx.request.body
        await db.POINT_ORDER.findOneAndUpdate
            _id: monk.id orderid
        ,
            $set:
                addressInfo: addressInfo
        ctx.body = status: true

    checkOrder: (ctx) ->
        { orderid } = ctx.request.body
        order = await db.POINT_ORDER.findOne _id: monk.id orderid
        if order.checked
            return (ctx.body = status: false, msg: "该订单已核销")

        await db.POINT_ORDER.findOneAndUpdate
            _id: monk.id orderid
        ,
            $set:
                checked: true
                checkTime: new Date()
        ctx.body = status: true

    consumeDraw: (ctx) ->
        drawid = ctx.params.drawid
        draw = await db.POINT_DRAW.findOne _id: monk.id drawid, deleted: $ne: true
        return (ctx.body = status: false, msg: "活动已结束") unless draw and draw.status is 0

        clientid = draw.clientid
        client = await db.CLIENT.findOne clientid

        user = ctx.session.user

        exists = _.find draw.users, (u) ->
            return u._id.toString() is user._id.toString()
        if exists
            return (ctx.body = status: false, msg: "已参与抽奖")

        if __lock[user._id]
            return (ctx.body = status: false, msg: "操作过快")

        __lock[user._id] = true

        setTimeout(
            ->
                __lock[user._id] = false
        ,
            2000
        )

        pointData =
            await db.POINT_DATA.findOne
                contactid: user.contactid
                clientid: draw.clientid
        unless pointData
            return (ctx.body = status: false, msg: "积分不足")
        unless draw.point <= pointData.point
            return (ctx.body = status: false, msg: "积分不足")

        user.time = new Date()
        draw =
            await db.POINT_DRAW.findOneAndUpdate
                _id: draw._id
            ,
                $push:
                    users: user

        await db.POINT_LOG.insert
            contactid: user.contactid
            clientid: clientid
            point: -draw.point
            desc: "参与抽奖 " + draw.name

        await db.POINT_DATA.findOneAndUpdate
            contactid: user.contactid
            clientid: clientid
        ,
            $inc: point: -draw.point * 1

        ctx.body = status: true, draw: draw

    consume: (ctx) ->
        itemid = ctx.params.itemid
        item = await db.POINT_ITEM.findOne _id: monk.id itemid
        return (ctx.body = status: false, msg: "商品不存在") unless item

        clientid = item.clientid
        client = await db.CLIENT.findOne clientid
        user = ctx.session.user

        if __lock[user._id]
            return (ctx.body = status: false, msg: "操作过快")

        __lock[user._id] = true

        setTimeout(
            ->
                __lock[user._id] = false
        ,
            2000
        )

        pointData =
            await db.POINT_DATA.findOne
                contactid: user.contactid
                clientid: item.clientid
        unless pointData
            return (ctx.body = status: false, msg: "积分不足")
        unless item.point <= pointData.point
            return (ctx.body = status: false, msg: "积分不足")

        if item.stock <= 0
            return (ctx.body = status: false, msg: "库存不足")

        if item.limit == "once"
            exists =
                await db.POINT_ORDER.count
                    itemid: item._id
                    userid: user._id
                    completed: true
            return (ctx.body = status: false, msg: "限领一次") if exists

        if item.limit == "eachday"
            exists =
                await db.POINT_ORDER.count
                    itemid: item._id
                    userid: user._id
                    date: dayjs().format "YYYY-MM-DD"
                    completed: true

            return (ctx.body = status: false, msg: "每日限领一次") if exists

        if item.limit == "eachweek"
            start = dayjs().startOf('week').format "YYYY-MM-DD"
            end = dayjs().endOf('end').format "YYYY-MM-DD"
            exists =
                await db.POINT_ORDER.count
                    itemid: item._id
                    userid: user._id
                    date:
                        $gte: start
                        $lte: end
                    completed: true

            return (ctx.body = status: false, msg: "每周限领一次") if exists

        if item.limit == "eachmonth"
            start = dayjs().startOf('month').format "YYYY-MM-DD"
            end = dayjs().endOf('month').format "YYYY-MM-DD"
            exists =
                await db.POINT_ORDER.count
                    itemid: item._id
                    userid: user._id
                    date:
                        $gte: start
                        $lte: end
                    completed: true

            return (ctx.body = status: false, msg: "每月限领一次") if exists

        if item.type is "red"
            if item.red_money2
                item.red_money1 = item.red_money
                item.red_money = _.floor _.random(item.red_money1, item.red_money2), 2

            return (ctx.body = status: false, msg: "商家红包余额不足，请稍后再领取") unless (
                client.red_fee >
                item.red_money * 100
            )

        if item.type is "code"
            codes = item.codes
            code = codes.pop()
            await db.POINT_ITEM.findOneAndUpdate
                _id: item._id
            ,
                $set:
                    codes: codes
                    code: code
                $push:
                    openCodes: code

            delete item.codes
            delete item.openCodes
            item.code = code

        order =
            await db.POINT_ORDER.insert
                itemid: item._id
                clientid: item.clientid
                userid: user._id
                openid: user.openid
                contactid: user.contactid
                date: dayjs().format "YYYY-MM-DD"
                createTime: new Date()
                point: item.point
                item: item

        if item.type is "red"
            res =
                await utils.wepay.transfer
                    partner_trade_no: order._id.toString()
                    openid: user.openid
                    check_name: "NO_CHECK"
                    amount: parseInt item.red_money * 100
                    desc: "领取红包"
                    spbill_create_ip: ctx.ip
            { xml } = await utils.xml2js res

            await db.POINT_ORDER.findOneAndUpdate { _id: order._id }, $set: payment: xml
            unless xml.return_code is "SUCCESS" and xml.result_code is "SUCCESS"
                return (ctx.body = status: false, msg: xml.err_code_des)

            await db.CLIENT.findOneAndUpdate
                _id: client._id
            ,
                $inc:
                    red_fee: parseInt -item.red_money * 100

        await db.POINT_LOG.insert
            contactid: user.contactid
            clientid: clientid
            point: -item.point
            desc: "兑换奖励 " + item.name

        await db.POINT_DATA.findOneAndUpdate
            contactid: user.contactid
            clientid: clientid
        ,
            $inc: point: -item.point * 1

        await db.POINT_ITEM.findOneAndUpdate
            _id: item._id
        ,
            $inc:
                stock: -1

        await db.POINT_ORDER.findOneAndUpdate order._id, $set: completed: true
        ctx.body = status: true, item: item

    # openred: (ctx) ->
